#include "../include/Server.h"
#include <algorithm>
#include <cstdlib>
#include <fstream>
#include <ostream>
#include <string>
#include <utility>
#include <vector>

std::pair<ULL, ULL> hash(const std::string &fish) {
  ULL base1 = 31;
  ULL base2 = 37;
  ULL res1 = 0, res2 = 0;
  for (const auto &i : fish) {
    res1 = base1 * res1 + (i - 'a');
    res2 = base2 * res2 + (i - 'a');
  }
  return std::make_pair(res1, res2);
}

void Server::init_user_pool() {
  std::ifstream fs("./data/用户.txt");
  std::string trash;
  std::getline(fs, trash);
  int i = 0;
  while (!fs.eof()) {
    auto new_user = new User;
    new_user->from_file(fs);
    std::ifstream cart_f("./data/" + new_user->name + ".txt");
    if (cart_f.fail()) {
      write_cart(new_user);
      cart_f.open("./data/" + new_user->name + ".txt");
    }
    i++;    
    key_pool.push_back(new_user->keys);
    new_user->user_cart.from_file(cart_f);
    cart_f.close();
    user_pool.push_back(new_user);
    std::cout << "已载入用户: \e[34m" << new_user->name << "\e[0m" << std::endl;
  }
  fs.close();
}

bool Server::admin_login(const std::string &name, const std::string &psw) {
  admin = Admin::admin_login(name, psw);
  if (!admin) {
    return false;
  }
  return true;
}

void Server::admin_logout() {
  delete admin;
  admin = nullptr;
}

void Server::init_sold_list() {
  std::ifstream fs("./data/已售清单.txt");
  sold_list.from_file(fs, 1);
  fs.close();
}

void Server::init_inventory() {
  std::ifstream f("./data/库存.txt");
  invent.from_file(f);
  f.close();
}

bool Server::user_login(const std::string &name, const std::string &psw) {
  auto fish = std::find_if(user_pool.begin(), user_pool.end(),
                           [name](User *a) { return a->name == name; });
  if (fish == user_pool.end()) {
    return false;
  }
  if ((*fish)->keys == hash(psw)) {
    current_user = *fish;
    return true;
  }
  return false;
}

bool Server::user_sign_up(const std::string &name, const std::string &psw) {

  auto same_person = std::find_if(user_pool.begin(), user_pool.end(),
                                  [name](User *u) { return u->name == name; });
  if (same_person != user_pool.end()) {
    return false;
  }
  User *u = new User(name, hash(psw));
  user_pool.push_back(u);
  current_user = u; //注册完成, 登录成功
  write_user();
  write_cart(u);
  return true;
}

void Server::user_logout() { current_user = nullptr; }

const cart Server::admin_view(bool is_inventory) {
  cart res;
  if (is_inventory) {
    auto in = invent.goods;
    for (auto i : in) {
      if (i.quantity >= 0) {
        res.add_good(i);
      }
    }
    return res;
  }
  return sold_list;
}

void Server::admin_add_good(const good &g) {
  invent.add_good(g);
  write_inventory();
}

int Server::admin_del_good(int index) {
  auto it = std::find_if(invent.goods.begin(), invent.goods.end(),
                         [index](good b) -> bool { return b.id == index; });
  if (it == invent.goods.end()) {
    return -114514;
  }
  auto a = *it;
  int code = invent.del_good(a);
  if (code) {
    return code;
  } else {
    //查找购物车，如果存在删除的这个商品就删掉
    for (auto &fish : user_pool) {
      auto &fish_cart = fish->user_cart.goods;
      auto target = std::find(fish_cart.begin(), fish_cart.end(), a);
      if (target != fish_cart.end()) {
        fish_cart.erase(target); //你会永远失去它！（真的很久!）
      }
    }
    write_inventory();
    for (auto i : user_pool) {
      write_cart(i);
    }
    return 0;
  }
}

void Server::admin_change_price(int new_price, int index) {
  auto it = std::find_if(invent.goods.begin(), invent.goods.end(),
                         [index](good b) -> bool { return b.id == index; });
  if (it == invent.goods.end()) {
    return;
  }
  it->price = new_price;
  for (auto &fish : user_pool) {
    auto &fish_cart = fish->user_cart.goods;
    auto target = std::find(fish_cart.begin(), fish_cart.end(), *it);
    if (target != fish_cart.end()) {
      target->price = new_price;
    }
  }
  write_inventory();
}

void Server::admin_change_quantity(int new_quan, int index) {
  auto it = std::find_if(invent.goods.begin(), invent.goods.end(),
                         [index](good b) -> bool { return b.id == index; });
  if (it == invent.goods.end()) {
    return;
  }
  it->quantity = new_quan;
  write_inventory();
}

const cart Server::view_invent() {
  cart res;
  for (auto i : invent.goods) {
    if (i.quantity > 0) {
      res.add_good(i);
    }
  }
  return res;
}

const cart Server::user_find(std::string target, std::string option,
                             bool (*selector)(std::string name,
                                              std::string option,
                                              const good &g)) {
  cart res;
  for (auto i : invent.goods) {
    if (selector(target, option, i) && i.quantity > 0) {
      res.add_good(i);
    }
  }
  std::sort(res.goods.begin(), res.goods.end(),
            [target](const good &a, const good &b) -> bool {
              return grade(a.name, target) > grade(b.name, target);
            });
  return res;
}

const cart Server::user_view_cart() {
  return user_find(
      "UshioAkaiwa", "",
      [](std::string a, std::string, const good &g) -> bool { return true; });
}

int Server::user_add_cart(good g) {
  auto found =
      std::find(invent.goods.begin(), invent.goods.end(), g); //寻找库存
  int user_quan;
  auto user_found = std::find(current_user->user_cart.goods.begin(),
                              current_user->user_cart.goods.end(),
                              g); //寻找用户是否已经添加过该商品
  if (user_found != current_user->user_cart.goods.end()) {
    user_quan = user_found->quantity;
  } else {
    user_quan = 0;
  }
  if (found != invent.goods.end() &&
      found->quantity >= g.quantity + user_quan) {
    int i = g.quantity;
    g = *found;
    g.quantity = i;
    current_user->add_good(g);
    write_cart(current_user);
    return 0;
  }
  if (found == invent.goods.end())
    return 1;
  else
    return 2;
}

int Server::user_del_cart(std::string name, std::string brand, int num,
                          bool (*selector)(good &g, std::string name,
                                           std::string brand)) {
  auto tmp = user_view_cart().goods;
  for (auto &i : tmp) {
    if (selector(i, name, brand) && i.quantity > 0) {
      int u = current_user->del_good(i, num);
      if (u) {
        return u;
      };
    }
  }
  write_cart(current_user);
  return 0;
}

bool Server::user_purchase() {
  if(current_user->money < current_user->user_cart.cost()){
    return false;
  }
  current_user->money -= current_user->user_cart.cost();
  int cnt = 0;
  auto tmp = current_user->user_cart.goods;
  for (auto i : tmp) {
    if (i.quantity > 0) {
      invent.del_good(i, i.quantity);
      i.owner = current_user->name;
      sold_list.add_good(i, 1);
      i.owner = "";
      current_user->del_good(i, -1);
    }
  }
  write_inventory();
  write_sold_list();
  write_cart(current_user);
  write_user();
  return true;
}

void Server::feed_me(double count){
  current_user->money += count;
}

void Server::write_user() {
  std::ofstream fs("./data/用户.txt", std::ios::trunc);
  fs << "用户名	密码 持有货币";
  for (User *i : user_pool) {
    fs << '\n' << *i;
  }
  fs.close();
}

void Server::write_cart(User *sb) {
#ifdef DEBUG
  std::cout << "wirte\n";
  for (auto i : sb->user_cart.goods) {
    std::cout << i << std::endl;
  }
#endif
  std::ofstream fs("./data/" + sb->name + ".txt");
  sb->user_cart.to_file(fs, 0);
  fs.close();
}

void Server::write_inventory() {
  std::ofstream fs("./data/库存.txt");
#ifdef DEBUG
  std::cout << "store inventory : \n";
  for (auto i : invent.goods) {
    std::cout << i << std::endl;
  }
#endif
  invent.to_file(fs);
  fs.close();
}

void Server::write_sold_list() {
  std::ofstream fs("./data/已售清单.txt");
#ifdef DEBUG
  std::cout << "write sold list : \n";
  for (auto i : sold_list.goods) {
    std::cout << i << std::endl;
  }
#endif
  sold_list.to_file(fs, 1);
  fs.close();
}